/*-------------------------------------------------------------------------
 *
 * table.c
 *	  Generic routines for table related code.
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/access/table/table.c
 *
 *
 * NOTES
 *	  This file contains table_ routines that implement access to tables (in
 *	  contrast to other relation types like indexes) that are independent of
 *	  individual table access methods.
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "access/relation.h"
#include "access/table.h"
#include "storage/lmgr.h"


/* ----------------
 *		table_open - 通过关系OID打开一个表关系
 *
 *		这基本上是relation_open加上检查该关系
 *		不是索引或复合类型。 （调用者还应该
 *		检查它不是视图或外部表，然后再假设它有
 *		存储。）
 * ----------------
 */
Relation table_open(Oid fc_relationId, LOCKMODE fc_lockmode)
{
	Relation	fc_r;

	fc_r = relation_open(fc_relationId, fc_lockmode);

	if (fc_r->rd_rel->relkind == RELKIND_INDEX ||
		fc_r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
		ereport(ERROR,
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
				 errmsg("\"%s\" is an index",
						RelationGetRelationName(fc_r))));
	else if (fc_r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
		ereport(ERROR,
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
				 errmsg("\"%s\" is a composite type",
						RelationGetRelationName(fc_r))));

	return fc_r;
}


/* ----------------
 *		try_table_open - 通过关系OID打开一个表关系
 *
 *		与table_open相同，除了如果关系不存在
 *		返回NULL而不是失败。
 * ----------------
 */
Relation try_table_open(Oid fc_relationId, LOCKMODE fc_lockmode)
{
	Relation	fc_r;

	fc_r = try_relation_open(fc_relationId, fc_lockmode);

	/* 如果表不存在，则离开 */
	if (!fc_r)
		return NULL;

	if (fc_r->rd_rel->relkind == RELKIND_INDEX ||
		fc_r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
		ereport(ERROR,
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
				 errmsg("\"%s\" is an index",
						RelationGetRelationName(fc_r))));
	else if (fc_r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
		ereport(ERROR,
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
				 errmsg("\"%s\" is a composite type",
						RelationGetRelationName(fc_r))));

	return fc_r;
}

/* ----------------
 *		table_openrv - 打开由RangeVar节点指定的表关系
 *
 *		如上所述，但关系是由RangeVar指定的。
 * ----------------
 */
Relation table_openrv(const RangeVar *fc_relation, LOCKMODE fc_lockmode)
{
	Relation	fc_r;

	fc_r = relation_openrv(fc_relation, fc_lockmode);

	if (fc_r->rd_rel->relkind == RELKIND_INDEX ||
		fc_r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
		ereport(ERROR,
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
				 errmsg("\"%s\" is an index",
						RelationGetRelationName(fc_r))));
	else if (fc_r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
		ereport(ERROR,
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
				 errmsg("\"%s\" is a composite type",
						RelationGetRelationName(fc_r))));

	return fc_r;
}

/* ----------------
 *		table_openrv_extended - 打开由RangeVar节点指定的表关系
 *
 *		如上所述，但可选择在关系未找到时返回NULL而不是失败。
 * ----------------
 */
Relation table_openrv_extended(const RangeVar *fc_relation, LOCKMODE fc_lockmode,
					  bool fc_missing_ok)
{
	Relation	fc_r;

	fc_r = relation_openrv_extended(fc_relation, fc_lockmode, fc_missing_ok);

	if (fc_r)
	{
		if (fc_r->rd_rel->relkind == RELKIND_INDEX ||
			fc_r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("\"%s\" is an index",
							RelationGetRelationName(fc_r))));
		else if (fc_r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
			ereport(ERROR,
					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
					 errmsg("\"%s\" is a composite type",
							RelationGetRelationName(fc_r))));
	}

	return fc_r;
}

/* ----------------
 *		table_close - 关闭一个表
 *
 *		如果lockmode不是“NoLock”，我们将释放指定的锁。
 *
 *		注意，通常在relation_close之后保持锁是合理的；
 *		在这种情况下，锁将在事务结束时自动释放。
 *		----------------
 */
void table_close(Relation fc_relation, LOCKMODE fc_lockmode)
{
	relation_close(fc_relation, fc_lockmode);
}
